﻿/*
	wp8libflac project
	© Alovchin, 2014
*/

using System;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Storage.Streams;

namespace wp8.MediaHelpers
{
    public struct BufferSegment
    {
        private readonly IBuffer _buffer;
        private readonly uint _count;
        private readonly uint _offset;

        public BufferSegment(IBuffer buffer)
        {
            if (buffer == null)
                throw new ArgumentNullException("buffer");

            this._buffer = buffer;
            this._offset = 0;
            this._count = buffer.Length;
        }

        public BufferSegment(IBuffer buffer, uint offset, uint count)
        {
            if (buffer == null)
                throw new ArgumentNullException("buffer");
            if (buffer.Length - offset < count)
                throw new ArgumentException("Invalid offset or count specified.");

            this._buffer = buffer;
            this._offset = offset;
            this._count = count;
        }

        public IBuffer Buffer
        {
            get
            {
                Contract.Assert(
                    (null == this._buffer && 0 == this._offset && 0 == this._count) ||
                    (null != this._buffer && this._offset + this._count <= this._buffer.Length),
                    "BufferSegment is invalid");

                return this._buffer;
            }
        }

        public uint Offset
        {
            get
            {
                Contract.Assert(
                    (null == this._buffer && 0 == this._offset && 0 == this._count) ||
                    (null != this._buffer && this._offset + this._count <= this._buffer.Length),
                    "BufferSegment is invalid");

                return this._offset;
            }
        }

        public uint Count
        {
            get
            {
                Contract.Assert(
                    (null == this._buffer && 0 == this._offset && 0 == this._count) ||
                    (null != this._buffer && this._offset + this._count <= this._buffer.Length),
                    "BufferSegment is invalid");

                return this._count;
            }
        }

        public override int GetHashCode()
        {
            return this._buffer == null ? 0 : unchecked((int)(this._buffer.GetHashCode() ^ this._offset ^ this._count));
        }

        public override bool Equals(Object obj)
        {
            return obj is BufferSegment && this.Equals((BufferSegment)obj);
        }

        public bool Equals(BufferSegment obj)
        {
            return (obj._buffer == this._buffer || obj._buffer.IsSameData(this._buffer)) && obj._offset == this._offset && obj._count == this._count;
        }

        public static bool operator ==(BufferSegment left, BufferSegment right)
        {
            return left.Equals(right);
        }

        public static bool operator !=(BufferSegment left, BufferSegment right)
        {
            return !(left == right);
        }
    }
}
